<!DOCTYPE html>
<html>
<head>
    <title>Physics Diagram - Spring on a Cylinder</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f0f0f0;
        }
        canvas {
            border: 1px solid #ccc;
            background-color: #fff;
        }
    </style>
</head>
<body>
    <canvas id="physicsCanvas" width="550" height="500"></canvas>
    <script>
        const canvas = document.getElementById('physicsCanvas');
        const ctx = canvas.getContext('2d');

        // Helper function to draw an arrow
        function drawArrow(fromx, fromy, tox, toy, headlen = 10) {
            const dx = tox - fromx;
            const dy = toy - fromy;
            const angle = Math.atan2(dy, dx);
            ctx.beginPath();
            ctx.moveTo(fromx, fromy);
            ctx.lineTo(tox, toy);
            ctx.moveTo(tox, toy);
            ctx.lineTo(tox - headlen * Math.cos(angle - Math.PI / 6), toy - headlen * Math.sin(angle - Math.PI / 6));
            ctx.moveTo(tox, toy);
            ctx.lineTo(tox - headlen * Math.cos(angle + Math.PI / 6), toy - headlen * Math.sin(angle + Math.PI / 6));
            ctx.stroke();
        }
        
        // Helper function to draw a spring (zigzag line)
        function drawSpring(x1, y1, x2, y2, coils = 25, width = 14) {
            const dx = x2 - x1;
            const dy = y2 - y1;
            const length = Math.sqrt(dx * dx + dy * dy);
            const angle = Math.atan2(dy, dx);

            ctx.save();
            ctx.translate(x1, y1);
            ctx.rotate(angle);
            ctx.beginPath();
            ctx.moveTo(0, 0);

            const step = length / (coils + 0.5);
            for (let i = 0; i < coils; i++) {
                const x = (i + 0.5) * step;
                const y = (i % 2 === 0) ? -width/2 : width/2;
                ctx.lineTo(x, y);
            }
            ctx.lineTo(length, 0);
            ctx.stroke();
            ctx.restore();
        }

        // --- Main Drawing ---

        // Style settings
        ctx.strokeStyle = 'black';
        ctx.fillStyle = 'black';
        ctx.lineWidth = 2;

        // Parameters
        const O = { x: 270, y: 200 };
        const R = 100;
        const theta = Math.PI / 4; // 45 degrees

        // --- 1. Draw the cylindrical structure ---
        // Filled background
        ctx.fillStyle = '#E8E8E8'; // Light gray fill
        ctx.beginPath();
        const structureBottomY = O.y + 120;
        ctx.arc(O.x, O.y, R, Math.PI, 0, false);
        ctx.lineTo(O.x + R, structureBottomY);
        ctx.lineTo(O.x - R, structureBottomY);
        ctx.closePath();
        ctx.fill();

        // Outline
        ctx.strokeStyle = 'black';
        ctx.lineWidth = 2.5;
        ctx.beginPath();
        ctx.moveTo(O.x - R, structureBottomY);
        ctx.lineTo(O.x - R, O.y);
        ctx.arc(O.x, O.y, R, Math.PI, 0, false);
        ctx.lineTo(O.x + R, O.y);
        ctx.lineTo(O.x + R, structureBottomY);
        ctx.stroke();
        
        // --- 2. Define key points ---
        const B = { x: O.x + R, y: O.y };
        const C = { x: O.x + R * Math.cos(theta), y: O.y - R * Math.sin(theta) };
        const A = { x: O.x + R, y: structureBottomY };

        // --- 3. Draw the block (m) ---
        ctx.save();
        ctx.translate(C.x, C.y);
        ctx.rotate(-theta); // Align with the tangent
        ctx.fillStyle = '#A9A9A9'; // Gray for the block
        ctx.strokeStyle = 'black';
        ctx.lineWidth = 1.5;
        const blockWidth = 30;
        const blockHeight = 22;
        ctx.fillRect(-blockWidth / 2, -blockHeight / 2, blockWidth, blockHeight);
        ctx.strokeRect(-blockWidth / 2, -blockHeight / 2, blockWidth, blockHeight);
        ctx.restore();
        
        ctx.font = 'italic 20px Arial';
        ctx.fillText('m', C.x + 10, C.y - 20);

        // --- 4. Draw the spring ---
        // Spring attaches to the center of the right face of the block
        const springAttachX = C.x + (blockWidth/2) * Math.cos(theta);
        const springAttachY = C.y - (blockWidth/2) * Math.sin(theta);
        ctx.lineWidth = 2;
        drawSpring(A.x, A.y, springAttachX, springAttachY, 25, 14);

        // --- 5. Draw the force F ---
        // Force starts from the center of the left face of the block
        const forceStartX = C.x - (blockWidth/2) * Math.cos(theta);
        const forceStartY = C.y + (blockWidth/2) * Math.sin(theta);
        
        const forceLength = 60;
        // Tangent direction vector is (-sin(theta), -cos(theta)) in canvas space for up-left motion
        const F_dx = -Math.sin(theta);
        const F_dy = -Math.cos(theta);
        const forceEndX = forceStartX + forceLength * F_dx;
        const forceEndY = forceStartY + forceLength * F_dy;
        
        ctx.lineWidth = 2;
        drawArrow(forceStartX, forceStartY, forceEndX, forceEndY);
        ctx.font = 'italic 22px Arial';
        ctx.fillText('F', forceEndX - 25, forceEndY - 5);
        
        // --- 6. Draw labels and guides ---
        ctx.lineWidth = 1;
        // Dashed line from O to B
        ctx.save();
        ctx.beginPath();
        ctx.setLineDash([5, 5]);
        ctx.moveTo(O.x, O.y);
        ctx.lineTo(B.x, B.y);
        ctx.stroke();
        ctx.restore();
        
        // Line OC (Radius)
        ctx.beginPath();
        ctx.moveTo(O.x, O.y);
        ctx.lineTo(C.x, C.y);
        ctx.stroke();
        
        // Angle arc for theta
        ctx.beginPath();
        ctx.arc(O.x, O.y, 30, -theta, 0);
        ctx.stroke();

        // Text labels
        ctx.font = 'italic 20px Arial';
        ctx.fillText('O', O.x - 20, O.y + 15);
        ctx.fillText('R', O.x + R*0.5*Math.cos(theta) - 20, O.y - R*0.5*Math.sin(theta));
        ctx.fillText('C', C.x - 25, C.y - 5);
        ctx.fillText('θ', O.x + 35, O.y - 8);
        
        ctx.font = '20px Arial';
        ctx.fillText('B', B.x + 8, B.y + 8);
        ctx.fillText('A', A.x - 25, A.y + 5);

        // "原长" (original length) annotation
        ctx.font = '18px "SimSun", "Microsoft YaHei"';
        const dimX = B.x + 25;
        const yTop = B.y;
        const yLineEnd = yTop + 70;
        ctx.fillText('原长', dimX + 10, yTop + 45);
        
        ctx.beginPath();
        // Vertical line
        ctx.moveTo(dimX, yTop);
        ctx.lineTo(dimX, yLineEnd);
        // T-bar at top
        ctx.moveTo(dimX - 5, yTop);
        ctx.lineTo(dimX + 5, yTop);
        // Upward pointing arrow on the line, mimicking the strange original diagram
        const arrowTipY = yLineEnd - 10;
        ctx.moveTo(dimX - 4, arrowTipY + 8);
        ctx.lineTo(dimX, arrowTipY);
        ctx.lineTo(dimX + 4, arrowTipY + 8);
        ctx.stroke();
        
        // --- 7. Bottom Title ---
        ctx.font = '22px "SimSun", "Microsoft YaHei"';
        ctx.fillStyle = 'black';
        ctx.textAlign = 'center';
        ctx.fillText('习题 2-15 图', canvas.width / 2, canvas.height - 20);

    </script>
</body>
</html>